import dash
import pandas as pd
from dash import html
import feffery_antd_charts as fact
import feffery_antd_components as fac
from dash.dependencies import Input, Output, State

# 读入原始数据
raw_stock_data = pd.read_csv('A股_股票日线行情数据_20220223_20220311.csv',
                             dtype={'股票代码': 'str'},
                             parse_dates=['交易日期'])

stock_data = raw_stock_data.copy()

stock_data['交易日期'] = stock_data['交易日期'].dt.strftime('%Y-%m-%d')

stock_data = (
    stock_data
        .groupby(['TS代码', '股票代码', '股票名称', '地域', '所属行业', '上市时间'])
        .apply(
        lambda df: (
            df
                .sort_values('交易日期')
                .agg({
                '收盘价': lambda s: s.tolist(),
                '涨跌额': lambda s: s.tolist(),
                '涨跌幅': lambda s: s.tolist(),
                '成交量（手）': lambda s: s.tolist(),
                '成交额（千元）': lambda s: s.tolist()
            })
        )
    )
        .reset_index(drop=False)
)

stock_data['周期涨幅'] = stock_data['收盘价'].apply(lambda l: (l[-1] - l[0]) / l[0])

app = dash.Dash(__name__, update_title=None)

app.title = '股票分析应用'

app.layout = html.Div(
    [
        fac.AntdRow(
            [
                fac.AntdCol(
                    html.Div(
                        [
                            fac.AntdAlert(
                                message=[
                                    '通过点击下表每行左侧单选框，选择你需要进一步分析的股票',
                                    '更多dash应用开发专业知识欢迎关注公众号【玩转dash】'
                                ],
                                showIcon=True,
                                messageRenderMode='loop-text'
                            ),
                            fac.AntdTable(
                                id='all-stocks-info-table',
                                columns=[
                                    {
                                        'title': '股票名称',
                                        'dataIndex': '股票名称',
                                        'fixed': 'left',
                                        'width': 100
                                    },
                                    {
                                        'title': 'TS代码',
                                        'dataIndex': 'TS代码',
                                        'width': 100
                                    },
                                    {
                                        'title': '股票代码',
                                        'dataIndex': '股票代码',
                                        'width': 100
                                    },
                                    {
                                        'title': '地域',
                                        'dataIndex': '地域',
                                        'width': 100
                                    },
                                    {
                                        'title': '所属行业',
                                        'dataIndex': '所属行业',
                                        'width': 100
                                    },
                                    {
                                        'title': '上市时间',
                                        'dataIndex': '上市时间',
                                        'width': 100
                                    },
                                    {
                                        'title': '收盘价',
                                        'dataIndex': '收盘价',
                                        'width': 100,
                                        'renderOptions': {
                                            'renderType': 'mini-area'
                                        }
                                    },
                                    {
                                        'title': '涨跌额',
                                        'dataIndex': '涨跌额',
                                        'width': 100,
                                        'renderOptions': {
                                            'renderType': 'mini-area'
                                        }
                                    },
                                    {
                                        'title': '涨跌幅',
                                        'dataIndex': '涨跌幅',
                                        'width': 100,
                                        'renderOptions': {
                                            'renderType': 'mini-area'
                                        }
                                    },
                                    {
                                        'title': '成交量（手）',
                                        'dataIndex': '成交量（手）',
                                        'width': 100,
                                        'renderOptions': {
                                            'renderType': 'mini-bar'
                                        }
                                    },
                                    {
                                        'title': '成交额（千元）',
                                        'dataIndex': '成交额（千元）',
                                        'width': 100,
                                        'renderOptions': {
                                            'renderType': 'mini-bar'
                                        }
                                    }
                                ],
                                sortOptions={
                                    'sortDataIndexes': ['上市时间']
                                },
                                filterOptions={
                                    '股票代码': {
                                        'filterMode': 'keyword'
                                    },
                                    'TS代码': {
                                        'filterMode': 'keyword'
                                    },
                                    '地域': {},
                                    '所属行业': {},
                                    '股票名称': {
                                        'filterMode': 'keyword'
                                    }
                                },
                                rowSelectionType='radio',
                                maxWidth=1100,
                                data=stock_data.to_dict('records'),
                                bordered=True,
                                miniChartHeight=25,
                                pagination={
                                    'pageSize': 15,
                                    'showSizeChanger': False,
                                    'showQuickJumper': True,
                                    'showTotalPrefix': '共有股票 ',
                                    'showTotalSuffix': ' 只'
                                }
                            )
                        ],
                        style={
                            'boxShadow': '0 6px 16px rgb(107 147 224 / 14%)',
                            'borderRadius': '10px',
                            'padding': '20px',
                            'height': '100%'
                        }
                    ),
                    span=12
                ),

                fac.AntdCol(
                    [
                        html.Div(
                            fac.AntdEmpty(
                                description='请先在左侧表格中选择要分析的股票！'
                            ),
                            id='single-stock-describe',
                            style={
                                'boxShadow': '0 6px 16px rgb(107 147 224 / 14%)',
                                'borderRadius': '10px',
                                'height': 'calc(50% - 10px)',
                                'marginBottom': '20px',
                                'display': 'flex',
                                'alignItems': 'center',
                                'justifyContent': 'center'
                            }
                        ),
                        html.Div(
                            fac.AntdEmpty(
                                description='请先在左侧表格中选择要分析的股票！'
                            ),
                            id='single-stock-chart',
                            style={
                                'boxShadow': '0 6px 16px rgb(107 147 224 / 14%)',
                                'borderRadius': '10px',
                                'height': 'calc(50% - 10px)',
                                'display': 'flex',
                                'alignItems': 'center',
                                'justifyContent': 'center',
                                'padding': '25px'
                            }
                        )
                    ],
                    span=12
                )
            ],
            gutter=25,
            style={
                'height': '100%'
            }
        )
    ],
    style={
        'padding': '25px 100px',
        'height': '100vh'
    }
)


@app.callback(
    [Output('single-stock-describe', 'children'),
     Output('single-stock-chart', 'children')],
    Input('all-stocks-info-table', 'selectedRows')
)
def analysis_selected_stock(selectedRows):
    if selectedRows:
        selected_single_stock_info = (
            raw_stock_data
                .query('TS代码 == "{}"'.format(selectedRows[0]['TS代码']))
                .reset_index(drop=True)
        )

        # 计算周期内当前个股在所有个股中的涨幅排名
        range_gains_rank = (
            stock_data
                .assign(排名=lambda df: df['周期涨幅'].rank(ascending=False, method='first'))
                .query('TS代码 == "{}"'.format(selectedRows[0]['TS代码']))
                .iat[0, -1]
        )

        # 计算周期内当前个股在所属行业内的涨幅排名
        industry_range_gains_rank = (
            stock_data
                .query('所属行业 == "{}"'.format(selectedRows[0]['所属行业']))
                .assign(排名=lambda df: df['周期涨幅'].rank(ascending=False, method='first'))
                .query('TS代码 == "{}"'.format(selectedRows[0]['TS代码']))
                .iat[0, -1]
        )

        # 计算周期内当前个股在所属区域内的涨幅排名
        area_range_gains_rank = (
            stock_data
                .query('地域 == "{}"'.format(selectedRows[0]['地域']))
                .assign(排名=lambda df: df['周期涨幅'].rank(ascending=False, method='first'))
                .query('TS代码 == "{}"'.format(selectedRows[0]['TS代码']))
                .iat[0, -1]
        )

        return [
            fac.AntdSpace(
                [
                    fac.AntdSpace(
                        [
                            fac.AntdTooltip(
                                fac.AntdProgress(
                                    percent=round(100 * (1 - range_gains_rank / stock_data.shape[0]), 2),
                                    type='dashboard',
                                    width=200
                                ),
                                title='大盘内阶段涨幅超越的个股比例'
                            ),
                            fac.AntdTooltip(
                                fac.AntdProgress(
                                    percent=round(
                                        100 * (1 - industry_range_gains_rank /
                                               stock_data.query('所属行业 == "{}"'.format(selectedRows[0]['所属行业'])).shape[
                                                   0]),
                                        2
                                    ),
                                    type='dashboard',
                                    width=200
                                ),
                                title='同行业内阶段涨幅超越的个股比例'
                            ),
                            fac.AntdTooltip(
                                fac.AntdProgress(
                                    percent=round(
                                        100 * (
                                                1 - area_range_gains_rank /
                                                stock_data.query('地域 == "{}"'.format(selectedRows[0]['地域'])).shape[0]
                                        ),
                                        2
                                    ),
                                    type='dashboard',
                                    width=200
                                ),
                                title='同地域内阶段涨幅超越的个股比例'
                            )
                        ],
                        size=50
                    )
                ]
            ),
            html.Div(
                fact.AntdStock(
                    data=selected_single_stock_info.to_dict('records'),
                    # 指定日期字段
                    xField='交易日期',
                    yAxis={
                        'label': {
                            'formatter': {
                                'func': '(value) => parseFloat(value).toFixed(2)'
                            }
                        }
                    },
                    autoFit=True,
                    # 指定开盘价字段, 收盘价字段, 最高价字段, 最低价字段
                    yField=['开盘价', '收盘价', '最高价', '最低价'],
                    legend={
                        'itemName': {
                            'formatter': {
                                'func': '''
                                            (name) => {
                                                return name === 'up' ? '上涨' : '下跌'
                                            }'''
                            }
                        }
                    }
                ),
                style={
                    'width': '100%',
                    'height': '100%'
                }
            )
        ]

    return dash.no_update


if __name__ == '__main__':
    app.run_server()
